using AutoMapper;
using Core.SimpleTemp.Common;
using Core.SimpleTemp.Common.PagingQuery;
using Core.SimpleTemp.Entitys;
using Core.SimpleTemp.Repositories;
using Core.Toolkit.Common;
using Core.Toolkit.Core;
using Core.Toolkit.Core.Api;
using Core.Toolkit.Core.Application;
using Core.Toolkit.Core.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Core.SimpleTemp.Application
{
    [AutoDi()]
    public class YH_ScreeningPlanService : BaseAppService<YH_ScreeningPlanDto, YH_ScreeningPlan, YH_ScreeningPlanRepository>
    {
        readonly ExcelHelp _excelHelp;
        readonly UserIdentity _userIdentity;
        public YH_ScreeningPlanService(YH_ScreeningPlanRepository repository, IHttpContextAccessor accessor, ExcelHelp excelHelp) : base(repository)
        {
            _excelHelp = excelHelp;
            _userIdentity = accessor?.HttpContext?.User?.GetUserIdentity();
        }

        #region Mobile

        private LoadPageOffsetModelAuto<YH_ScreeningPlan, YH_ScreeningPlanDto> GetLoadPageOffsetMode(PagingModel<YH_ScreeningPlanDto> pagingQueryModel)
        {
            var loadPageOffsetModel = this.GetLoadPageOffsetModelAuto(pagingQueryModel);
            var baseQuery = _repository.QueryBase().AsNoTracking();
            loadPageOffsetModel.QueryWhere = this.CreateQRList();

            //.Add("Unit","=") //排查单位
            //.Add("PersonInCharge","=") //负责人
            //.Add("YH_ScreeningPlanTask.Type","=") //隐患_排查计划任务主表 ->频次类别(年/月/日)
            //.Add("InvestigationPost","=") //排查岗位
            //.Add("StandardType","=") //排查标准类型
            //.YH_ScreeningPlanProject.涉及区域ID


            //.Add("Objective","=") //排查目的
            //.Add("Requirements","=") //排查要求
            //.Add("Content","=") //排查内容

            //.Add("Remark","=") //备注
            //.Add("IsNotRemind","=") //是否提醒
            //.Add("MoveUp","=") //提前提醒天数
            //.Add("Type","=") //提醒类别(年月)
            //.Add("BeginTime","=") //计划开始时间
            //.Add("IsProceed","=") //计划是否正在进行(进行中/关闭)
            //.Add("Status","=") //状态(保存/提交)
            //.Add("CreateFactory","=") //隶属工厂
            //.Add("CreateDept","=") //
            //.Add("UpdateDept","=") ;//


            loadPageOffsetModel.BasqQuery = baseQuery;
            loadPageOffsetModel.Order = orderModel => orderModel.CreateTime;
            //loadPageOffsetModel.Selector = model => new YH_ScreeningPlan()
            //{
            //    Id = model.Id,
            //    Unit = model.Unit,//排查单位,
            //    Objective = model.Objective,// 排查目的,
            //    PersonInCharge = model.PersonInCharge,//负责人,
            //    Requirements = model.Requirements,//排查要求,
            //    Content = model.Content,//排查内容,
            //    StandardType = model.StandardType,//排查标准类型,
            //    InvestigationPost = model.InvestigationPost,//排查岗位,
            //    Remark = model.Remark,//备注,
            //    IsNotRemind = model.IsNotRemind,//是否提醒,
            //    MoveUp = model.MoveUp,//提前提醒天数,
            //    Type = model.Type,//提醒类别(年月),
            //    BeginTime = model.BeginTime,//计划开始时间,
            //    IsProceed = model.IsProceed,//计划是否正在进行(进行中/关闭),
            //    Status = model.Status,//状态(保存/提交),
            //    CreateFactory = model.CreateFactory,//隶属工厂,
            //    CreateDept = model.CreateDept,//,
            //    UpdateDept = model.UpdateDept,//,
            //};
            return loadPageOffsetModel;
        }


        public async Task<IPageModel<YH_ScreeningPlanDto>> GetList(PagingModel<YH_ScreeningPlanDto> pagingQueryModel)
        {
            var loadPageOffsetModel = GetLoadPageOffsetMode(pagingQueryModel);
            return await base.LoadPageOffsetAsync(loadPageOffsetModel);
        }


        #endregion
        /// <summary>
        /// 隐患排查内容GetList
        /// </summary>
        /// <param name="pagingQueryModel"></param>
        /// <returns></returns>
        private LoadPageOffsetModel<YH_ScreeningPlan, YH_ScreeningPlanDto> GetLoadPageOffsetModelForPC(PagingModel<YH_ScreeningPlanDto> pagingQueryModel)
        {
            var loadPageOffsetModel = this.GetLoadPageOffsetModel(pagingQueryModel);
            var baseQuery = _repository.QueryBase().AsNoTracking().Include(a => a.SysUser)
                .Include(a => a.SysDepartment)
                .Include(a => a.YH_ScreeningPlanProject).ThenInclude(a => a.YH_ScreeningPlanProDetail)
                .Include(a => a.YH_ScreeningPlanProject)
                .Include(a => a.YH_ScreeningPlanUser);

            var dtoModel = pagingQueryModel.Model;

            var filterList = this.CreateQRList()
            .Add("Unit", "=") //排查单位
            .Add("PersonInCharge", "=") //负责人
            .Add("Objective", "in") //排查目的
            .Add("Content", "in"); //排查内容


            //工厂处理
            if (_userIdentity.Headoffice)
                filterList.Add("CreateFactory", "="); //总部从查询条件取工厂id
            else
                filterList.Add("CreateFactory", "=", _userIdentity.Factory);

            var filterExpre = filterList.BuildeQR(dtoModel.ToEntity<YH_ScreeningPlan>());


            //根据参与人id查询
            if (pagingQueryModel.Model.ParticipantID != null)
            {
                if (filterExpre == null) filterExpre = ExpressionExtension.True<YH_ScreeningPlan>();
                filterExpre = ExpressionExtension.And(filterExpre, a => a.YH_ScreeningPlanUser.Where(b => b.UserId == pagingQueryModel.Model.ParticipantID).Any());
            }


            //仅在ScreeningPerson不为null时查询，用于隐患排查时获取可看到的信息
            if (pagingQueryModel.Model.ScreeningPerson != null)
            {
                Expression<Func<YH_ScreeningPlan, bool>> where1 = a => a.PersonInCharge == dtoModel.ScreeningPerson;
                Expression<Func<YH_ScreeningPlan, bool>> where2 = a => a.YH_ScreeningPlanUser.Select(c => c.UserId).Contains(dtoModel.ScreeningPerson);
                if (filterExpre == null) filterExpre = ExpressionExtension.True<YH_ScreeningPlan>();
                filterExpre = ExpressionExtension.And(filterExpre, ExpressionExtension.Or(where1, where2));
            }









            loadPageOffsetModel.QueryWhere = filterExpre;
            loadPageOffsetModel.BasqQuery = baseQuery;
            //loadPageOffsetModel.Order = orderModel => orderModel.CreateTime;

            loadPageOffsetModel.OrderList = new List<OrderModel>()
            {
                new OrderModel(){ IsDesc=true,PropertyName="CreateTime"}
            };
            //loadPageOffsetModel.Selector = model => new YH_ScreeningPlan()
            //{
            //    Id = model.Id,
            //    Unit = model.Unit,//排查单位,
            //    Objective = model.Objective,// 排查目的,
            //    PersonInCharge = model.PersonInCharge,//负责人,
            //    Requirements = model.Requirements,//排查要求,
            //    Content = model.Content,//排查内容,
            //    StandardType = model.StandardType,//排查标准类型,
            //    InvestigationPost = model.InvestigationPost,//排查岗位,
            //    MoveUp = model.MoveUp,//提前提醒天数,
            //    Type = model.Type,//提醒类别(年月),
            //    BeginTime = model.BeginTime,//计划开始时间,
            //    ScreeningType = model.ScreeningType,//日常排查/计划排查
            //    YH_ScreeningPlanUser = model.YH_ScreeningPlanUser,//参与人对象集合
            //    YH_ScreeningPlanProject = model.YH_ScreeningPlanProject,//排查项目集合
            //    SysDepartment=model.SysDepartment
            //};
            return loadPageOffsetModel;
        }
        /// <summary>
        /// 排查计划修改
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<bool> UpdateForPCAsync(YH_ScreeningPlanDto dto)
        {


            return await _repository.UpdateForPCAsync(Mapper.Map<YH_ScreeningPlan>(dto));
        }

        /// <summary>
        /// PC的GetList
        /// </summary>
        /// <param name="pagingQueryModel"></param>
        /// <returns></returns>
        public async Task<IPageModel<YH_ScreeningPlanDto>> GetListForPC(PagingModel<YH_ScreeningPlanDto> pagingQueryModel)
        {
            var loadPageOffsetModel = GetLoadPageOffsetModelForPC(pagingQueryModel);
            return await base.LoadPageOffsetAsync(loadPageOffsetModel);
        }
        /// <summary>
        /// Get
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<YH_ScreeningPlanDto> GetAsync(Guid id)
        {
            var baseQuery = _repository.QueryBase().AsNoTracking()
                .Include(a => a.SysUser)
                .Include(a => a.SysDepartment)
                .Include(a => a.YH_ScreeningPlanProject).ThenInclude(a => a.YH_ScreeningPlanProDetail).ThenInclude(a => a.YH_Grade)
                .Include(a => a.YH_ScreeningPlanProject).ThenInclude(a => a.SysArea)
                .Include(a => a.YH_ScreeningPlanTask).ThenInclude(a => a.YH_ScreeningPlanWarn).ThenInclude(a => a.SysUser)
                .Include(a => a.YH_ScreeningPlanUser);



            var result = await GetAsync(id, baseQuery);
            return Mapper.Map<YH_ScreeningPlanDto>(result);
        }
        /// <summary>
        /// 逻辑删除，继承自基础服务类物理删除方法并重写调用基础仓储类逻辑删除方法
        /// </summary>
        /// <param name="ids"></param>
        /// <param name="autoSave"></param>
        /// <returns></returns>
        public override async Task DeleteBatchAsync(Guid[] ids, bool autoSave = true)
        {
            foreach (Guid item in ids)
            {
                //调用基础仓储类中的逻辑删除方法
                await _repository.DeleteLogicAsync(item);
            }
        }
        /// <summary>
        /// 导出
        /// </summary>
        /// <param name="pagingQueryModel"></param>
        /// <returns></returns>
        public async Task<string> Export(PagingModel<YH_ScreeningPlanDto> pagingQueryModel)
        {
            var loadPageOffsetModel = GetLoadPageOffsetModelForPC(pagingQueryModel);
            var DataList = await this.ExportDataAsync(loadPageOffsetModel);
            //拼接参与人员姓名
            DataList.ForEach(dto =>
            {
                var str = "";
                dto.YH_ScreeningPlanUser.ToList().ForEach(a =>
                {
                    str += a.UserText + ",";
                });
                if (str.Length > 0)
                    str = str.Substring(0, str.Length - 1);
                dto.Participant = str;

                dto.FrequencyText = ShowFrequencyText(dto);

                dto.YH_ProjectAndDetail = new List<YH_ProjectAndDetail>();
                dto.YH_ScreeningPlanProject.ToList().ForEach(project =>
                {
                    project.YH_ScreeningPlanProDetail.ToList().ForEach(detail =>
                    {
                        dto.YH_ProjectAndDetail.Add(new YH_ProjectAndDetail()
                        {
                            ScreeningPlanId = dto.Id,
                            Project = project.Project,
                            Region = project.Region,
                            Remark = project.Remark,
                            SysArea = project.SysArea,
                            ScreeningPlanProjectId = project.Id,
                            SearchMajorCode = detail.SearchMajorCode,
                            StandardID = detail.StandardID,
                            StandardContent = detail.StandardContent,
                            Type = detail.Type,
                            CreateFactory = detail.CreateFactory,
                            RiskLevel = detail.RiskLevel,
                            RiskLevelText = detail.RiskLevelText
                        });
                    });
                });
            });
            var excelData = DataList.Select(model => new
            {
                Unit = model.SysDepartment?.Name,
                Unit_title = "排查单位",
                model.Objective,
                Objective_title = "排查目的",
                PersonInCharge = model.PersonInChargeText,
                PersonInCharge_title = "负责人",
                model.Participant,
                Participant_title = "参与人",
                model.Requirements,
                Requirements_title = "排查要求",
                model.Content,
                Content_title = "排查内容",
                StandardType = model.StandardTypeText,
                StandardType_title = "排查标准类型",
                model.InvestigationPost,
                InvestigationPost_title = "排查岗位",
                model.ScreeningType,
                ScreeningType_title = "排查类型",
                Frequency = model.FrequencyText,
                Frequency_title = "提醒频次",
            }).ToList();




            return _excelHelp.Create(excelData);
        }
        /// <summary>
        /// 格式化频次文本
        /// </summary>
        /// <returns></returns>
        public string ShowFrequencyText(YH_ScreeningPlanDto dto)
        {
            string result = "";

            if (dto.ScreeningType == "计划排查")
            {
                var moveUp = "，提前" + dto.MoveUp + "天提醒";
                if (dto.MoveUp == 0 || dto.MoveUp == null)
                {
                    moveUp = "，不提醒";
                }
                switch (dto.Type)
                {
                    case "0": result = "每年执行1次" + moveUp; break;
                    case "1": result = "每月执行1次" + moveUp; break;
                    case "2": result = "每周执行1次" + moveUp; break;
                    case "3": result = "每天执行1次"; break;
                    case "4": result = "在" + dto.BeginTimeByCustom?.ToString() + "执行1次" + moveUp; break;
                    default: result = "数据异常"; break;
                }
            }
            else
            {
                result = "每天执行1次";
            }
            return result;
        }
        /// <summary>
        /// 计算下次执行时间
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public DateTime ComputeRunTime(YH_ScreeningPlanDto dto)
        {
            if (dto.ScreeningType == "日常排查") dto.Type = "3";
            DateTime Now = DateTime.Now;
            DateTime NowTime = new DateTime();
            int month, day, week;
            #region
            //判断执行日期类别
            switch (dto.Type)
            {
                //年
                case "0":
                    month = dto.Month.Value;
                    day = dto.Day.Value;
                    NowTime = new DateTime(Now.Year, month, day, 0, 0, 0);
                    if (NowTime <= Now)
                        NowTime = NowTime.AddYears(1);
                    break;
                //月
                case "1":
                    day = dto.Day.Value;
                    NowTime = new DateTime(Now.Year, Now.Month, day, 0, 0, 0);
                    if (NowTime <= Now)
                        NowTime = NowTime.AddMonths(1);
                    break;
                //周
                case "2":
                    DateTime startWeek = Now.AddDays(1 - Convert.ToInt32(Now.DayOfWeek.ToString("d")));  //本周周一
                    int weekNum = int.Parse(Now.DayOfWeek.ToString("d"));//今天星期几
                    week = dto.Week.Value;//星期几执行
                    DateTime DoTime = startWeek.AddDays((week - 1));  //本周week日期
                    NowTime = new DateTime(DoTime.Year, DoTime.Month, DoTime.Day, 0, 0, 0);
                    if (week <= weekNum)
                        NowTime = NowTime.AddDays(7);
                    break;
                case "3":
                    NowTime = dto.BeginTime.Value;
                    if (NowTime <= Now)
                        return NowTime;
                    break;
                case "4":
                    NowTime = dto.BeginTimeByCustom.Value;
                    if (NowTime <= Now)
                        return NowTime;
                    break;
                default:
                    break;
            }
            #endregion
            if (NowTime <= Now && dto.Type != "4" && dto.Type != "3")
            {
                NowTime = ComputeRunTime(dto);
            }
            return NowTime;
        }
        /// <summary>
        /// 初始化提醒表信息
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public List<YH_ScreeningPlanTaskDto> CreateYH_ScreeningPlanTask(YH_ScreeningPlanDto dto)
        {
            //日常排查不提醒
            if (dto.ScreeningType == "日常排查") return null;
            List<YH_ScreeningPlanTaskDto> entities = new List<YH_ScreeningPlanTaskDto>();
            //仅提醒负责人
            var YH_ScreeningPlanWarn = new List<YH_ScreeningPlanWarnDto>()
                {
                    new YH_ScreeningPlanWarnDto()
                    {
                        UserId=dto.PersonInCharge,
                        IsRead=false
                    }
                };
            //提前提醒天数小于0则不提前提醒
            if (dto.MoveUp > 0)
            {
                var entity1 = new YH_ScreeningPlanTaskDto()
                {
                    WarnType = "提前",
                    WarnTime = dto.NowTime.Value.AddDays(-dto.MoveUp.Value),
                    WarnContent = dto.MoveUp.ToString() + "天后执行排查计划",
                    YH_ScreeningPlanWarn = YH_ScreeningPlanWarn
                };
                entities.Add(entity1);
            }
            var entity2 = new YH_ScreeningPlanTaskDto()
            {
                WarnType = "到期",
                WarnTime = dto.NowTime,
                WarnContent = "执行排查计划",
                YH_ScreeningPlanWarn = YH_ScreeningPlanWarn
            };

            entities.Add(entity2);
            return entities;
        }
        /// <summary>
        /// 模型转换：
        /// 根据YH_ProjectAndDetail集合，转化为YH_ScreeningPlanProject
        /// </summary>
        /// <param name="padList"></param>
        /// <returns></returns>
        public List<YH_ScreeningPlanProject> ConvertFromProjectAndDetail(List<YH_ProjectAndDetail> padList)
        {
            if (padList.Count == 0) return null;
            List<YH_ScreeningPlanProject> sppList = new List<YH_ScreeningPlanProject>();

            for (int i = 0; i < padList.Count; i++)
            {
                YH_ScreeningPlanProDetail sppd = new YH_ScreeningPlanProDetail()
                {

                };
            }
            return sppList;
        }


    }

}
